package com.jubotech.framework.netty.async;

import java.time.LocalDateTime;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.Message;
import com.jubotech.business.web.domain.CommonState;
import com.jubotech.business.web.domain.SysAutoSetting;
import com.jubotech.business.web.domain.WxAccountInfo;
import com.jubotech.business.web.domain.WxContactInfo;
import com.jubotech.business.web.domain.WxMessageInfo;
import com.jubotech.business.web.service.CommonStateService;
import com.jubotech.business.web.service.KeyWordsService;
import com.jubotech.business.web.service.SysAutoSettingService;
import com.jubotech.business.web.service.WxAccountService;
import com.jubotech.business.web.service.WxContactService;
import com.jubotech.business.web.service.WxMessageService;
import com.jubotech.framework.common.AutoType;
import com.jubotech.framework.netty.utils.ByteStringToString;
import com.jubotech.framework.netty.utils.MessageUtil;
import com.jubotech.framework.netty.utils.MsgIdBuilder;
import com.jubotech.framework.netty.utils.NettyConnectionUtil;
import com.jubotech.framework.util.EmojiFilter;
import com.jubotech.framework.util.JsonUtils;
import com.jubotech.framework.util.MessageSendUtils;

import Jubo.JuLiao.IM.Wx.Proto.AgreeJoinChatRoomTask.AgreeJoinChatRoomTaskMessage;
import Jubo.JuLiao.IM.Wx.Proto.FriendAddNotice.FriendAddNoticeMessage;
import Jubo.JuLiao.IM.Wx.Proto.FriendAddNotice.FriendMessage;
import Jubo.JuLiao.IM.Wx.Proto.FriendAddReqeustNotice.FriendAddReqeustNoticeMessage;
import Jubo.JuLiao.IM.Wx.Proto.FriendPushNotice.FriendPushNoticeMessage;
import Jubo.JuLiao.IM.Wx.Proto.FriendTalkNotice.FriendTalkNoticeMessage;
import Jubo.JuLiao.IM.Wx.Proto.SendLuckyMoneyTask.SendLuckyMoneyTaskMessage;
import Jubo.JuLiao.IM.Wx.Proto.TakeLuckyMoneyTask.TakeLuckyMoneyTaskMessage;
import Jubo.JuLiao.IM.Wx.Proto.TalkToFriendTask.TalkToFriendTaskMessage;
import Jubo.JuLiao.IM.Wx.Proto.TransportMessageOuterClass.EnumContentType;
import Jubo.JuLiao.IM.Wx.Proto.TransportMessageOuterClass.EnumMsgType;
import Jubo.JuLiao.IM.Wx.Proto.TransportMessageOuterClass.TransportMessage;
import Jubo.JuLiao.IM.Wx.Proto.WeChatOfflineNotice.WeChatOfflineNoticeMessage;
import Jubo.JuLiao.IM.Wx.Proto.WeChatTalkToFriendNotice.WeChatTalkToFriendNoticeMessage;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

@Service
@EnableAsync
@Slf4j
public class AsyncTaskService {
 
	@Resource
	private WxMessageService weChatMessageService;
	@Resource
	private WxContactService weChatContactService;
	@Resource
	private WxAccountService weChatAccountService;
	@Resource
	private SysAutoSettingService sysAutoSettingService;
	@Resource
	private KeyWordsService keyWordsService;
	@Resource
	private CommonStateService commonStateService;
	 

	/**
	 * 自动抢红包、自动收账
	 * @param ctx
	 * @param type
	 * @param req
	 * @param accessToken
	 * @param msgId
	 */
	private static void takeLuckyMoney(ChannelHandlerContext ctx,Integer type,FriendTalkNoticeMessage req,String accessToken,long msgId){
		String content = ByteStringToString.bytesToString(req.getContent(), "utf-8");
		if(type == AutoType.AUTOTYPE_LUCKMONEY){//红包有个人红包和群红包
			if(!JsonUtils.isJson(content)){//群红包处理
				int index =  content.indexOf("{");
				if(index>0){
					content= content.substring(index,content.length());
				}
			}
		}
		JSONObject json = JSON.parseObject(content);
		String key = null;
		if (null != json) {
			key = json.get("Key").toString();
		}
		if (!StringUtils.isBlank(key)) {
			TakeLuckyMoneyTaskMessage.Builder bd = TakeLuckyMoneyTaskMessage.newBuilder();
			bd.setWeChatId(req.getWeChatId());
			bd.setFriendId(req.getFriendId());
			bd.setMsgSvrId(req.getMsgSvrId());
			bd.setMsgKey(key);
			bd.setTaskId(MsgIdBuilder.getId());
			TakeLuckyMoneyTaskMessage resp = bd.build();
			MessageUtil.sendMsg(ctx, EnumMsgType.TakeLuckyMoneyTask,accessToken,msgId,resp);
			return;
		}

	}

	/**
	 * 拦截手机端消息做一下自动功能
	 * @param ctx
	 * @param req
	 * @param accessToken
	 * @param msgId
	 */
	@Async
	public void msgAopTask(ChannelHandlerContext ctx, FriendTalkNoticeMessage req,String accessToken,long msgId) {

		try {
			log.info(LocalDateTime.now() + " msgAopTask 对应的线程名: " + Thread.currentThread().getName());
			if (req.getContentType().equals(EnumContentType.LuckyMoney)) {// 红包消息
				SysAutoSetting sys = sysAutoSettingService.findSettingByWcIdAutoType(req.getWeChatId(),AutoType.AUTOTYPE_LUCKMONEY);
				if (null != sys) {
					if (null != req.getContent()) {
						takeLuckyMoney(ctx, AutoType.AUTOTYPE_LUCKMONEY, req, accessToken, msgId);
					}
				}
			}

			if (req.getContentType().equals(EnumContentType.MoneyTrans)) {// 转账消息
				SysAutoSetting sys = sysAutoSettingService.findSettingByWcIdAutoType(req.getWeChatId(),AutoType.AUTOTYPE_MONEYTRANS);
				if (null != sys) {
					if (null != req.getContent()) {
						takeLuckyMoney(ctx, AutoType.AUTOTYPE_MONEYTRANS, req, accessToken, msgId);
					}
				}
			}

			if (req.getContentType().equals(EnumContentType.Link)) {// 链接消息，判断是否是群邀请链接
				String content = ByteStringToString.bytesToString(req.getContent(), "utf-8");
				if(!JsonUtils.isJson(content)){
					int index =  content.indexOf("{");
					if(index>0){
						content= content.substring(index,content.length());
					}
				}
				JSONObject json = JSON.parseObject(content);
				Object obj = json.get("Title");
				if (null != obj) {
					String title = obj.toString();
					if (title.contains("邀请你加入群聊")) {
						SysAutoSetting sys = sysAutoSettingService.findSettingByWcIdAutoType(req.getWeChatId(),AutoType.AUTOTYPE_GROUPINVITATION);
						if (null != sys) {
							String talker = req.getFriendId();
							AgreeJoinChatRoomTaskMessage.Builder bd = AgreeJoinChatRoomTaskMessage.newBuilder();
							bd.setWeChatId(req.getWeChatId());
							bd.setMsgSvrId(req.getMsgSvrId());
							bd.setTalker(talker);
							bd.setTaskId(MsgIdBuilder.getId());
							bd.setMsgContent(content);
							AgreeJoinChatRoomTaskMessage resp = bd.build();
							MessageUtil.sendMsg(ctx, EnumMsgType.AgreeJoinChatRoomTask,accessToken,msgId, resp);
							return;
						}
					}
				}
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}

	}

	/**
	 * 拦截手机端好友请求消息
	 * @param vo
	 * @param ctx
	 * @param req
	 */
	@Async
	public void msgAopTaskFriendAdd(TransportMessage vo,ChannelHandlerContext ctx, FriendAddReqeustNoticeMessage req) {
		try {
			log.info(LocalDateTime.now() + " msgAopTask 对应的线程名: " + Thread.currentThread().getName());
			SysAutoSetting sys = sysAutoSettingService.findSettingByWcIdAutoType(req.getWeChatId(),AutoType.AUTOTYPE_FRIENDREQEST);
			if (null != sys) {
				MessageSendUtils.throughFriendRequest(vo, req, ctx);
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}

	}




	/**
	 * 转发消息给pc客户端
	 *
	 * @param wechatId
	 * @param type
	 * @param req
	 */
	@Async
	public void msgSend2pc(String wechatId, EnumMsgType type, Message req) {

		try {
			log.info(LocalDateTime.now() + " msgSend2pc 什么也不做" + Thread.currentThread().getName());
			/*
			log.info(LocalDateTime.now() + " msgSend2pc 对应的线程名: " + Thread.currentThread().getName());
			// 先从缓存取，如果取不到再用sql取
			List<WeChatAccountInfo> accountInfoList = Constant.accountInfoList;
			if (null == accountInfoList || accountInfoList.size() == 0) {
				// 刷新缓存
				accountInfoList = weChatAccountService.refreshCache();
			}

			String account = null;
			//略过....//TODO
			if (!StringUtils.isBlank(account)) {
				// 转发给pc端
				ChannelHandlerContext chx = NettyConnectionUtil.getClientChannelHandlerContextByUserId(account);
				if (null != chx) {
					MessageUtil.sendJsonMsg(chx, type, NettyConnectionUtil.getNettyId(chx), null, req);
				}
			}
			*/
		} catch (Throwable e) {
			e.printStackTrace();
		}

	}

	/**
	 * 转发消息给手机客户端
	 *
	 * @param ctx
	 * @param wechatId
	 * @param type
	 * @param vo
	 * @param req
	 */
	@Async
	public void msgSend2Phone(ChannelHandlerContext ctx, String wechatId, EnumMsgType type, TransportMessage vo,Message req) {

		try {
			log.info(LocalDateTime.now() + " msgSend2Phone 对应的线程名: " + Thread.currentThread().getName());

			ChannelHandlerContext chx = NettyConnectionUtil.getClientChannelHandlerContextByUserId(wechatId);
			if (null != chx) {
				// 转发给手机端
				MessageUtil.sendMsg(chx, type, vo.getAccessToken(), null, req);
				// 告诉发送方 消息已经收到
				MessageUtil.sendJsonMsg(ctx, EnumMsgType.MsgReceivedAck, vo.getAccessToken(), vo.getId(), null);
			} else {
				 
				// 做个保护，如果微信不在线，则通知pc端，下线其微信
				WxAccountInfo account = weChatAccountService.findWeChatAccountInfoByWeChatId(wechatId);
				account.setIsonline(1);// 下线
				weChatAccountService.updateOnline(account);
				
				// 通知pc端下线其微信
				WeChatOfflineNoticeMessage resp = WeChatOfflineNoticeMessage.newBuilder().setWeChatId(wechatId).build();
				MessageUtil.sendJsonMsg(ctx, EnumMsgType.WeChatOfflineNotice, NettyConnectionUtil.getNettyId(ctx),null, resp);
				 
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

	/**
	 * 保存通讯录录列表数据
	 *
	 * @param req
	 * @param account
	 */
	@Async
	public void friendListSave(FriendPushNoticeMessage req, WxAccountInfo account) {
		log.info(LocalDateTime.now() + " friendListSave 对应的线程名: " + Thread.currentThread().getName());

		List<FriendMessage> friendList = req.getFriendsList();
		if (null != friendList && friendList.size() > 0) {
			String wechatId = req.getWeChatId();
			for (int i = 0; i < friendList.size(); i++) {
				FriendMessage friend = friendList.get(i);
				if (null != friend) {
					try {
						WxContactInfo contactinfo = weChatContactService.findContactinfoByfriendid(account.getCid(),
								wechatId, friend.getFriendId());
						if (null != contactinfo) {
							setContActinfo(contactinfo, friend);
							weChatContactService.update(contactinfo);
						} else {
							contactinfo = new WxContactInfo();
							setContActinfo(contactinfo, friend);
							contactinfo.setCid(account.getCid());
							contactinfo.setWechatid(req.getWeChatId());
							contactinfo.setFriendid(friend.getFriendId());
							weChatContactService.insert(contactinfo);
						}
					} catch (Throwable e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	private static void setContActinfo(WxContactInfo contactinfo, FriendMessage friend) {
		contactinfo.setFriend_wechatno(friend.getFriendNo());
		contactinfo.setNickname(EmojiFilter.containsEmoji(friend.getFriendNick()) ? EmojiFilter.filterEmoji(friend.getFriendNick()) : friend.getFriendNick());
		contactinfo.setGender(friend.getGenderValue());
		contactinfo.setAvatar(EmojiFilter.containsEmoji(friend.getAvatar()) ? EmojiFilter.filterEmoji(friend.getAvatar()) : friend.getAvatar());
		contactinfo.setRemark(EmojiFilter.containsEmoji(friend.getRemark()) ? EmojiFilter.filterEmoji(friend.getRemark()) : friend.getRemark());
		contactinfo.setCountry(friend.getCountry());
		contactinfo.setProvince(friend.getProvince());
		contactinfo.setCity(friend.getCity());
		contactinfo.setType(0);
	}

	/**
	 * 修改msgserverid
	 */
	@Async
	public void updateMsgServerId(String weChatId, String friendId, long msgId, long msgServerId) {
		try {
			log.info(LocalDateTime.now() + " updateMsgServerId 对应的线程名: " + Thread.currentThread().getName());
			WxMessageInfo msgInfo = weChatMessageService.queryWeChatMessageInfoByMsgServerId(weChatId, friendId,String.valueOf(msgId));
			if (null != msgInfo) {
				msgInfo.setMsgsvrid(String.valueOf(msgServerId));
				weChatMessageService.update(msgInfo);
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

	/**
	 * 保存消息
	 *
	 * @param account
	 * @param account
	 * @param req
	 */
	@Async
	public void saveMessage(WxAccountInfo account, FriendTalkNoticeMessage req) {
		try {
			log.info(LocalDateTime.now() + " saveMessage 对应的线程名: " + Thread.currentThread().getName());
			if(req.getFriendId().contains("@chatroom")) {
				log.info("群消息丢弃【{}】", req.getContent().toStringUtf8());
				return;
			}

			WxMessageInfo info = new WxMessageInfo();
			String content = ByteStringToString.bytesToString(req.getContent(), "utf-8");
			info.setCid(account.getCid());
			info.setWechatid(req.getWeChatId());
			info.setFriendid(req.getFriendId());
			info.setMsgsvrid(String.valueOf(req.getMsgSvrId()));
			info.setIssend("false");// 收到的消息
			info.setContenttype(req.getContentTypeValue());
			info.setContent(EmojiFilter.containsEmoji(content) ? EmojiFilter.filterEmoji(content) : content);// base64了 需要解码存储
			if(req.getFriendId().contains("chatroom")){
				info.setType(1);
			}else{
				info.setType(0);
			}
			weChatMessageService.insert(info);
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

	/**
	 * 保存发送消息
	 *
	 * @param req
	 */
	@Async
	public void savePcMessage(TalkToFriendTaskMessage req) {
		log.info(LocalDateTime.now() + " savePcMessage 对应的线程名: " + Thread.currentThread().getName());
		WxAccountInfo account = weChatAccountService.findWeChatAccountInfoByWeChatId(req.getWeChatId());
		if (null != account) {
			try {
				WxMessageInfo info = new WxMessageInfo();
				String content = ByteStringToString.bytesToString(req.getContent(), "utf-8");
				info.setCid(account.getCid());
				info.setWechatid(req.getWeChatId());
				info.setFriendid(req.getFriendId());
				info.setMsgsvrid(String.valueOf(req.getMsgId()));
				info.setIssend("true");// 发送
				info.setContenttype(req.getContentTypeValue());
				info.setContent(EmojiFilter.containsEmoji(content) ? EmojiFilter.filterEmoji(content) : content);// base64了 需要解码存储
				if(req.getFriendId().contains("chatroom")){
					info.setType(1);
				}else{
					info.setType(0);
				}
				weChatMessageService.insert(info);
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 手机上回复了好友消息，消息记录上传
	 * @param req
	 */
	@Async
	public  void savePhoneSendMessage(WeChatTalkToFriendNoticeMessage req){
	    	WxAccountInfo  account = weChatAccountService.findWeChatAccountInfoByWeChatId(req.getWeChatId());
	    	if(null != account){
	    		try {
					WxMessageInfo info = new WxMessageInfo();
					String content = ByteStringToString.bytesToString(req.getContent(), "utf-8");
					info.setCid(account.getCid());
					info.setWechatid(req.getWeChatId());
					info.setFriendid(req.getFriendId());
					info.setMsgsvrid(String.valueOf(req.getMsgSvrId()));
					info.setIssend("true");//发送
					info.setContenttype(req.getContentTypeValue());
					info.setContent(content);//base64了 需要解码存储
					if(req.getFriendId().contains("chatroom")){
						info.setType(1);
					}else{
						info.setType(0);
					}
					weChatMessageService.insert(info);
				} catch (Exception e) {
					e.printStackTrace();
				}
	    	}
	}

	/**
	 * 保存红包消息
	 *
	 * @param req
	 * @param content
	 */
	@Async
	public void saveLuckyMoneyMessage(SendLuckyMoneyTaskMessage req, String content) {
		log.info(LocalDateTime.now() + " saveLuckyMoneyMessage 对应的线程名: " + Thread.currentThread().getName());
		WxAccountInfo wechat = weChatAccountService.findWeChatAccountInfoByWeChatId(req.getWeChatId());
		if (null != wechat) {
			try {
				WxMessageInfo info = new WxMessageInfo();
				info.setCid(wechat.getCid());
				info.setWechatid(req.getWeChatId());
				info.setFriendid(req.getFriendId());
				info.setMsgsvrid(String.valueOf(req.getTaskId()));
				info.setIssend("true");// 发送
				info.setContenttype(11);
				info.setContent(content);
				weChatMessageService.insert(info);
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
	}
	

	/**
	 * 拦截新增好友
	 * @param req
	 */
	@Async
	public  void aopFriendAddMsg(FriendAddNoticeMessage req){
    	try {
    		WxAccountInfo account = weChatAccountService.findWeChatAccountInfoByWeChatId(req.getWeChatId());
    		if(null == account){
    			return;
    		}
			CommonState state = commonStateService.queryCommonStateByCid(account.getCid(), AutoType.AUTOTYPE_BYREQUESTAFTER);
			if(null != state){
				MessageUtil.sendTextMsg(req.getWeChatId(),req.getFriend().getFriendId(),state.getReturnString());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
	
	/**
	 * 保存新增好友数据
	 * @param req
	 */
	@Async
	public  void saveFriendAddContactinfo(FriendAddNoticeMessage req){
    	try {
    		WxAccountInfo account = weChatAccountService.findWeChatAccountInfoByWeChatId(req.getWeChatId());
    		if(null == account){
    			return;
    		}
			//新增好友
			FriendMessage  friend = req.getFriend();
			WxContactInfo   contactinfo = weChatContactService.findContactinfoByfriendid(account.getCid(),req.getWeChatId(),friend.getFriendId());
			if(null != contactinfo){
				setContActinfo(contactinfo, friend);
				weChatContactService.update(contactinfo);
			}else{
				
				//通过好友后的回复
	    		aopFriendAddMsg(req);
				
				contactinfo = new WxContactInfo();
				setContActinfo(contactinfo, friend);
				contactinfo.setCid(account.getCid());
				contactinfo.setWechatid(req.getWeChatId());
				contactinfo.setFriendid(friend.getFriendId());
				weChatContactService.insert(contactinfo);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
	 
	@Async
	public void msgAopProcessing(TransportMessage vo, FriendTalkNoticeMessage req, WxAccountInfo account) {
		//不要急，一步一步慢慢来 //TODO
		//1、先判断是否是群消息，群消息丢弃
		//2、再判断是否配关键词，若是关键词，回复关键词相应内容
		//没用的东西不要回复，免得打扰好友
		//如果FriendId包含@chatroom说明是群消息
		if(req.getFriendId().contains("@chatroom")) {
			log.info("群消息丢弃【{}】", req.getContent().toStringUtf8());
			return;
		}

		if (req.getContentTypeValue() != 1 || req.getMsgSvrId() == 0) {
			log.info("【{}】消息丢弃【{}】", req.getContentTypeValue(), req.getContent().toStringUtf8());
			return;
		}
 
	  
		//关键字
		String message = req.getContent().toStringUtf8();
		String keyString = keyWordsService.checkKeyWord(message, account);
		if (StringUtils.isNotEmpty(keyString)) {
			MessageSendUtils.sendMessage(req.getWeChatId(),req.getFriendId(),keyString);
			return;
		}
         log.info("无用消息丢弃【{}】", req.getContent().toStringUtf8());
		 
	}

}
